package com.admin.service.impl;

import com.admin.common.CommonUtils;
import com.admin.common.biz.ModelUseStatus;
import com.admin.persistence.sys.entity.PersonUser;
import com.admin.persistence.sys.entity.User;
import com.admin.persistence.sys.mapper.PersonMapper;
import com.admin.persistence.sys.mapper.PersonUserMapper;
import com.admin.persistence.sys.mapper.UserMapper;
import com.admin.service.SysRoleService;
import com.admin.service.SysUserService;
import com.admin.service.vo.SysRole;
import com.admin.service.vo.SysUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Data
@AllArgsConstructor
@Service
public class SysUserServiceImp implements SysUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PersonMapper personMapper;

    @Autowired
    private PersonUserMapper personUserMapper;

    @Autowired
    private SysRoleService sysRoleService;

    @Transactional
    @Override
    public SysUser createSysUser(SysUser sysUser) {
        User user = sysUser.getUser();
        if (canUseAccount(user.getAccount()) && saveSysUser(sysUser) > 0) {
            return sysUser;
        }
        return null;
    }

    @Override
    public SysUser queryById(String id) {
        User user = userMapper.selectById(id);
        if (user == null) return null;
        List<SysRole> sysRoles = sysRoleService.queryByAccount(user.getAccount());

        if (!CollectionUtils.isEmpty(sysRoles)) {
            return new SysUser(user, sysRoles.stream().map(cur -> {
                return cur.getRole();
            }).collect(Collectors.toList()));
        }
        return new SysUser(user, null);
    }

    @Transactional
    @Override
    public int saveSysUser(SysUser sysUser) {
        User user = sysUser.getUser();
        String id = user.getId(), account = user.getAccount();
        if (!StringUtils.isEmpty(id) && queryById(id) != null) {
            return userMapper.updateById(user);
        }
        if (!StringUtils.isEmpty(account) && queryByAccount(account) == null) {
            user.setId(CommonUtils.createId());
            return userMapper.insert(user);
        }
        return 0;
    }

    @Override
    public SysUser queryByAccount(String account) {
        QueryWrapper queryWrapper = new QueryWrapper<User>().eq("ACCOUNT", account);
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) return null;
        List<SysRole> sysRoles = sysRoleService.queryByAccount(user.getAccount());

        if (!CollectionUtils.isEmpty(sysRoles)) {
            return new SysUser(user, sysRoles.stream().map(cur -> {
                return cur.getRole();
            }).collect(Collectors.toList()));
        }
        return new SysUser(user, null);
    }

    @Override
    public List<SysUser> queryListByPersonInfo(String personId, List<String> personIds, String name, String emial,
                                               String idCard, String phone, boolean use) {
        List<SysUser> sysUsers = new ArrayList<SysUser>();
        List<User> users = userMapper.queryListByPersonInfo(personId, personIds, name, emial, idCard, phone, use);
        if (!CollectionUtils.isEmpty(users)) {
            users.stream().forEach(cur -> {
                sysUsers.add(queryById(cur.getId()));
            });
        }
        return sysUsers;
    }

    @Transactional
    @Override
    public int editionSysUser(SysUser sysUser) {
        return userMapper.updateById(sysUser.getUser());
    }

    @Transactional
    @Override
    public int removeSysUser(SysUser sysUser) {
        sysUser.getUser().setStatus(ModelUseStatus.REMVOE.value);
        return userMapper.updateById(sysUser.getUser());
    }

    @Override
    public boolean canUseAccount(String account) {
        if (StringUtils.isEmpty(account)) return false;
        QueryWrapper queryWrapper = new QueryWrapper<User>().eq("ACCOUNT", account);
        return CollectionUtils.isEmpty(userMapper.selectList(queryWrapper)) || queryByAccount(account) == null;
    }

    @Override
    public boolean canBeUse(String userId) {
        return userMapper.selectById(userId) != null
                &&
                CollectionUtils.isEmpty(personUserMapper.selectList(new QueryWrapper<PersonUser>().eq("USER_ID", userId)));
    }

    @Transactional
    @Override
    public List<String> bindPerson(List<String> personIds, List<String> userIds) {
        List<String> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(personIds) && !CollectionUtils.isEmpty(userIds)) {
            personIds.stream().forEach(curPersonId -> {
                userIds.stream().filter(curUserId -> canBeUse(curUserId)).forEach(curUserId_ -> {
                    if (personUserMapper.insert(new PersonUser(CommonUtils.createId(), curPersonId, curUserId_)) > 0) {
                        result.add(curUserId_);
                    }
                });
            });
        }
        return result;
    }

    @Transactional
    @Override
    public List<String> unbindPerson(List<String> personIds) {
        List<String> result = new ArrayList<>();
        Optional.ofNullable(personIds).ifPresent(cur -> {
            cur.stream().forEach(curId -> {
                if (personUserMapper.delete(Wrappers.<PersonUser>lambdaQuery().eq(PersonUser::getPersonId, curId)) > 0) {
                    result.add(curId);
                }
            });
        });
        return result;
    }

}
